//----------------------------------------------------------------------------------------------
//	Filename:	TreePointCloud.h
//	Author:		Sandro Spina
//	Date:		01/08/2012
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
#pragma once

#include "Shape/PointCloud.h"

namespace Illumina 
{
	namespace Core
	{
		//----------------------------------------------------------------------------------------------		
		struct TreePointCloudStatistics 
		{
			int m_internalNodeCount,
				m_leafNodeCount,
				m_maxTreeDepth,
				m_minTreeDepth,
				m_pointCount,
				m_maxLeafPointCount,
				m_minLeafPointCount,
				m_intersectionCount;

			TreePointCloudStatistics(void);

			std::string ToString(void) const;
		};

		//----------------------------------------------------------------------------------------------
		class ITreePointCloud 
			: public IPointCloud
		{
		public:
			//----------------------------------------------------------------------------------------------
			// Enumeration for representing tree node types 
			//----------------------------------------------------------------------------------------------
			enum NodeType
			{
				Internal,
				Leaf
			};

		protected:
			//----------------------------------------------------------------------------------------------
			// Enumeration for selecting partitioning type
			//----------------------------------------------------------------------------------------------
			enum PartitionType
			{
				SpatialMedian,
				SurfaceAreaHeuristic
			};

		protected:
			//----------------------------------------------------------------------------------------------
			// Bookkeeping information on tree-based acceleration structure
			//----------------------------------------------------------------------------------------------
			TreePointCloudStatistics m_statistics;
		
		protected:
			ITreePointCloud(const std::string& p_strName);
			ITreePointCloud(void);

			void ComputeBounds(const List<int> &p_objectList, AxisAlignedBoundingBox &p_aabb, 
				float p_fMinEpsilon = 0.0f, float p_fMaxEpsilon = 0.0f);

			void ComputeBounds(int p_from, int p_to, AxisAlignedBoundingBox &p_aabb,
				float p_fMinEpsilon = 0.0f, float p_fMaxEpsilon = 0.0f);

			int DistributeUnique(const List<int> &p_objectList, float p_fPartition, int p_nAxis, 
				List<int> &p_outLeftList, List<int> &p_outRightList);

			int Distribute(const List<int> &p_objectList, float p_fPartition, int p_nAxis, 
				List<int> &p_outLeftList, List<int> &p_outRightList);

			int Distribute(const List<int> &p_objectList, 
				AxisAlignedBoundingBox &p_leftAABB, AxisAlignedBoundingBox &p_rightAABB, 
				List<int> &p_outLeftList, List<int> &p_outRightList);


			float FindPartitionPlane(const List<int> &p_objectList, AxisAlignedBoundingBox &p_aabb, 
				int p_nAxis, PartitionType p_partitionType);

			float FindPartitionPlaneSpatialMedian(const List<int> &p_objectList, 
				AxisAlignedBoundingBox &p_aabb, int p_nAxis);
			
			float FindPartitionPlaneSAH(const List<int> &p_objectList, 
				AxisAlignedBoundingBox &p_aabb, int p_nAxis);
		};
		//----------------------------------------------------------------------------------------------
	}
}